package Executor;


import interfaces.PrimeCounter;
import interfaces.PrimeFinder;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

public class PrimeCounterImpl implements PrimeCounter {

    ExecutorService threadPool;
    PrimeFinder finder;

    @Override
    public void setPrimeFinder(PrimeFinder tester) {
        this.finder = tester;
    }

    @Override
    public void setThreadPool(ExecutorService threadPool) {
        this.threadPool = threadPool;

    }

    @Override
    public int count(int start, int end, int numberOfThreads) {

        try {

            int result = 0;

            if (numberOfThreads == 1) {
                Counter counter = new Counter(start, end, finder);
                result = counter.call();
            } else {
                List<Future<Integer>> tasks = new ArrayList<Future<Integer>>(
                        numberOfThreads);
                result++;
                int numbers = (end - start) / numberOfThreads;
                for (int i = 0; i < numberOfThreads; i++) {
                    int currentStart = numbers * (i - 1) + 1;

                    int currEnd = numbers * i;

                    Counter counter = new Counter(currentStart, currEnd, finder);
                    Future<Integer> future = threadPool.submit((Callable<Integer>) counter);
                    tasks.add(future);
                }

                for (Future<Integer> task : tasks) {
                    result += task.get();

                }
            }
            return result;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }


}
